package com.fer.andenginemvc.api.gameObjects;

import java.util.HashMap;

import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.shape.IAreaShape;
import org.andengine.entity.sprite.Sprite;
import org.andengine.extension.physics.box2d.PhysicsConnector;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;

import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;

public abstract class GameObject<T extends IAreaShape> {

	public static HashMap<Body, GameObject<? extends IAreaShape>> bodyMap = new HashMap<Body, GameObject<? extends IAreaShape>>();
	
	public T entity;
	public Body body;
	protected FixtureDef fixtureDef;
	
	protected VertexBufferObjectManager vbom;
	protected PhysicsWorld physWorld;
	protected PhysicsConnector connector;
	
	public GameObject(PhysicsWorld world, VertexBufferObjectManager vbom, T entity) {
		this.physWorld = world;
		this.vbom = vbom;
		this.entity = entity;
		
		init();
	}
	
	protected static IAreaShape getSprite(float width, float height,
			ITextureRegion texture, float x, float y, VertexBufferObjectManager vbom) {
		Rectangle rect = new Rectangle(x, y, width, height, vbom);
		rect.setAlpha(1f);
		Sprite sprite = new Sprite(x, y, texture, vbom);
		sprite.setWidth(width);
		sprite.setHeight(height);
		rect.attachChild(sprite);
		return rect;
	}
	
	protected Sprite attachSprite(ITextureRegion texture, float x, float y)
	{
		entity.setAlpha(0f);
		Sprite sprite = new Sprite(x, y, texture, vbom);
		sprite.setWidth(entity.getWidth());
		sprite.setHeight(entity.getHeight());
		entity.attachChild(sprite);
		return sprite;
	}
	
	public void init()
	{
		fixtureDef = initFixtureDef();
		body = initBody();
		connector = new PhysicsConnector(entity, body, true, true);
		
		bodyMap.put(body, this);
		entity.setVisible(true);
		physWorld.registerPhysicsConnector(connector);
		connector.setUpdatePosition(true);
		body.setActive(true);
		entity.setIgnoreUpdate(false);		
	}
	
	public Body initBody()
	{
		return PhysicsFactory.createBoxBody(physWorld, entity, BodyType.DynamicBody, fixtureDef);
	}
	public abstract FixtureDef initFixtureDef();
	
	/**
	 * This method is called when the current game object collides with another game obejct
	 * @param go
	 */
	public void onCollision(GameObject<?> go){};
	
	public boolean die()
	{
		if (entity.isVisible()) {

	        GameObject.bodyMap.remove(body);
	        entity.setVisible(false);
            physWorld.unregisterPhysicsConnector(connector);
            connector.setUpdatePosition(false);
            body.setActive(false);
            entity.setIgnoreUpdate(true);
            return true;
	    }
		return false;
	}
	
	protected <O> O get(Class<O> clazz, GameObject<?> go)
	{
		return clazz.cast(go);
	}
	
}
